<template>
  <div style="height: 100%">
    <DesignForm ref="designFormRef" />
    <!-- <FormPreviewDrawer @register="registerDrawer" /> -->
  </div>
</template>
<script lang="ts" setup>
  import { noHaveTableAndField, remoteComponents } from '/@/components/Designer';
  import DesignForm from './Designer.vue';
  // import FormPreviewDrawer from '/@/components/Designer/src/components/FormPreviewDrawer.vue';
  import { inject, ref, Ref } from 'vue';

  import { GeneratorConfig } from '/@/model/generator/generatorConfig';
  import { TableFieldConfig } from '/@/model/generator/tableStructureConfig';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { ComponentOptionModel, FormJson } from '/@/model/generator/codeGenerator';
  import { unionWith } from 'lodash-es';
  import {
    noHaveField,
    shortTextComponents,
    longTextComponents,
    integerComponents,
    decimalsComponents,
    dateTimeComponents,
    timeComponents,
  } from '/@/components/Designer';
  import { useI18n } from '/@/hooks/web/useI18n';
  const { t } = useI18n();
  const generatorConfig = inject<GeneratorConfig>('generatorConfig');
  const designType = inject<Ref<string>>('designType');
  const isCustomForm = inject<boolean>('isCustomForm', false);

  const { notification } = useMessage();

  const designFormRef = ref();
  const rangeComponents = ['time-range', 'date-range'];

  const setStructureConfig = () => {
    generatorConfig!.tableStructureConfigs = [];
    let tableFieldConfigs = [] as TableFieldConfig[];

    getTableStructure(generatorConfig?.formJson.list, tableFieldConfigs);
    if (generatorConfig?.formJson.hiddenComponent?.length) {
      generatorConfig?.formJson.hiddenComponent.map((item) => {
        if (
          !generatorConfig?.tableStructureConfigs?.length ||
          !generatorConfig?.tableStructureConfigs[0]?.isMain
        ) {
          generatorConfig?.tableStructureConfigs?.unshift({
            tableName: item.bindTable,
            tableComment: '',
            isMain: true,
            tableFieldConfigs: [],
          });
        }
        if (generatorConfig?.tableStructureConfigs?.length) {
          generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.push({
            key: item.key,
            fieldName: item.bindField,
            fieldLength: 500,
            fieldType: 0,
            fieldComment: t('隐藏组件'),
          });
        }
      });
    }

    if (isCustomForm) {
      //自定义表单界面优先、简易模板开启了数据权限则新增rule_user_id字段
      if (generatorConfig?.isDataAuth) {
        const hasRuleUserField =
          generatorConfig?.tableStructureConfigs?.length &&
          generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.find(
            (x) => x.key === 'rule_user_id',
          );
        if (hasRuleUserField) return;
        generatorConfig?.tableStructureConfigs?.length &&
          generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.push({
            key: 'rule_user_id',
            fieldName: 'rule_user_id',
            fieldLength: 500,
            fieldType: 7,
            fieldComment: t('数据权限所属人ID'),
          });
      } else {
        if (generatorConfig?.tableStructureConfigs?.length) {
          generatorConfig.tableStructureConfigs[0].tableFieldConfigs =
            generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.filter(
              (x) => x.key !== 'rule_user_id',
            );
        }
      }
    }
  };

  const getTableStructure = (list, tableFieldConfigs) => {
    list?.map((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          getTableStructure(child.list, tableFieldConfigs);
        }
      } else if (item.type === 'form' || item.type === 'one-for-one') {
        let subTableFieldConfigs = [] as TableFieldConfig[];
        generatorConfig?.tableStructureConfigs?.push({
          key: item.key,
          tableName: item.bindTable,
          tableComment: '',
          isMain: false,
          tableFieldConfigs: subTableFieldConfigs,
        });
        if (item.type === 'form') {
          item.children?.map((subItem) => {
            if (!noHaveField.includes(subItem.type) || rangeComponents.includes(subItem.type)) {
              setTableFieldConfigs(subItem, subTableFieldConfigs);
            }
          });
        } else {
          getSimpleTableStructure(item.children, subTableFieldConfigs);
        }
      } else if (!noHaveField.includes(item.type) || rangeComponents.includes(item.type)) {
        if (
          !generatorConfig?.tableStructureConfigs?.length ||
          !generatorConfig?.tableStructureConfigs[0].isMain
        ) {
          generatorConfig?.tableStructureConfigs?.unshift({
            tableName: item.bindTable,
            tableComment: '',
            isMain: true,
            tableFieldConfigs,
          });
        }

        if (generatorConfig?.tableStructureConfigs?.length) {
          setTableFieldConfigs(item, generatorConfig?.tableStructureConfigs[0].tableFieldConfigs);
        }
      }
    });
  };
  const getSimpleTableStructure = (list, tableFieldConfigs) => {
    list?.map((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          getSimpleTableStructure(child.list, tableFieldConfigs);
        }
      } else if (!noHaveField.includes(item.type) || rangeComponents.includes(item.type)) {
        setTableFieldConfigs(item, tableFieldConfigs);
      }
    });
  };
  const setTableFieldConfigs = (item, tableFieldConfigs) => {
    if (rangeComponents.includes(item.type)) {
      tableFieldConfigs.push({
        key: item.key,
        fieldStartName: item.bindStartTime,
        fieldName: item.bindStartTime,
        fieldLength: !getFieldType(item.type) ? 500 : null,
        fieldType: getFieldType(item.type),
        fieldComment: t(`{types}开始时间`, { types: item.label }),
      });
      tableFieldConfigs.push({
        key: item.key,
        fieldEndName: item.bindEndTime,
        fieldName: item.bindEndTime,
        fieldLength: !getFieldType(item.type) ? 500 : null,
        fieldType: getFieldType(item.type),
        fieldComment: t(`{types}结束时间`, { types: item.label }),
      });
    } else if (item.type === 'info' && item.options.infoType === 2) {
      //信息体组件 选择当前时间情况
      tableFieldConfigs.push({
        key: item.key,
        fieldName: item.bindField,
        fieldLength: null,
        fieldType: 5,
        fieldComment: item.label!,
      });
    } else {
      tableFieldConfigs.push({
        key: item.key,
        fieldName: item.bindField,
        fieldLength: !getFieldType(item.type) ? 500 : null,
        fieldType: getFieldType(item.type),
        fieldComment: item.label!,
      });
    }
  };

  const getFieldType = (type) => {
    switch (type) {
      case shortTextComponents.find((x) => x === type):
        return 0;
      case longTextComponents.find((x) => x === type):
        return 1;
      case integerComponents.find((x) => x === type):
        return 2;
      case decimalsComponents.find((x) => x === type):
        return 3;
      case dateTimeComponents.find((x) => x === type):
        return 5;
      case timeComponents.find((x) => x === type):
        return 8;
      default:
        return 0;
    }
  };

  //验证当前步骤的数据
  const validateStep = async (): Promise<boolean> => {
    if (designType!.value !== 'data') {
      setStructureConfig();
    }
    const formJson = designFormRef.value.getJson() as FormJson;

    //formJson 是否为空 或者 一个组件都没有
    if (!formJson || formJson.list.length === 0) {
      notification.error({
        message: t('提示'),
        description: t('表单设计不能为空！'),
      }); //提示消息
      return false;
    }

    const { tableConfigs } = generatorConfig as GeneratorConfig;
    const mainTableName = tableConfigs?.find((x) => x.isMain)?.tableName;

    //先判断所有非子表组件  是否包含主表字段  如果一个主表字段都没有 提示
    const getMainComponent = (list?) => {
      if (!list) return [];
      let mainComponents = [] as Recordable[];
      for (const item of list) {
        if (['tab', 'grid', 'card'].includes(item.type)) {
          for (const child of item.layout!) {
            mainComponents = unionWith(mainComponents, getMainComponent(child.list));
          }
        } else {
          if (item.bindTable === mainTableName) {
            mainComponents.push(item);
          }
        }
      }
      return mainComponents;
    };

    //获取子表中的字段
    const getSubField = (list) => {
      let subTableFieldList = {};
      for (const item of list) {
        if (['tab', 'grid', 'card'].includes(item.type)) {
          for (const child of item.layout!) {
            getSubField(child.list);
          }
        }
        if (item.type === 'form' || item.type === 'one-for-one') {
          if (!item.children.length) return;
          subTableFieldList[item.bindTable] = [];
          item.children.forEach((x) => {
            if (rangeComponents.includes(x.type)) {
              subTableFieldList[item.bindTable].push(x.bindStartTime);
              subTableFieldList[item.bindTable].push(x.bindEndTime);
            } else {
              if (x.bindField) subTableFieldList[item.bindTable].push(x.bindField);
            }
          });
        }
      }
      return subTableFieldList;
    };

    //判断子表的同一表中 是否有重复字段
    const subTableHasSameField = () => {
      const subTableFieldList = getSubField(formJson.list);
      const hasSameFieldList: boolean[] = [];
      if (!Object.keys(subTableFieldList!).length) return false;
      for (let key in subTableFieldList) {
        const res = subTableFieldList[key].length === new Set(subTableFieldList[key]).size;
        hasSameFieldList.push(res);
      }
      return hasSameFieldList.some((x) => !x);
    };

    //主表中的所有字段
    const mainTableFieldList: string[] = [];
    getMainComponent(formJson.list).forEach((item) => {
      if (rangeComponents.includes(item.type)) {
        mainTableFieldList.push(item.bindStartTime);
        mainTableFieldList.push(item.bindEndTime);
      } else {
        mainTableFieldList.push(item.bindField);
      }
    });

    //界面优先、简易模板 判断子表里面是否有组件
    const hasSubFormComponents = generatorConfig?.tableStructureConfigs
      ?.filter((x) => !x.isMain)
      .every((x) => !!x.tableFieldConfigs.length);

    if (!getMainComponent(formJson.list).length && designType!.value === 'data') {
      notification.error({
        message: t('提示'),
        description: t('表单设计未绑定一个主表字段，最少得包含一个主表字段！'),
      }); //提示消息
      return false;
    }
    if (
      generatorConfig?.tableStructureConfigs &&
      !generatorConfig?.tableStructureConfigs[0]?.isMain &&
      designType!.value !== 'data'
    ) {
      notification.error({
        message: t('提示'),
        description: t('表单设计未添加生成主表字段的组件，请先添加后再进行下一步。'),
      }); //提示消息
      return false;
    }
    //判断是否多表  但是没有子表单组件
    if (
      (designType!.value === 'data' &&
        tableConfigs!.length > 1 &&
        sumSubFormComponent(formJson.list) !== tableConfigs!.length - 1) ||
      (designType!.value !== 'data' && !hasSubFormComponents)
    ) {
      notification.error({
        message: t('提示'),
        description: t('有子表未绑定组件！'),
      }); //提示消息
      return false;
    }
    if (
      designType!.value === 'data' &&
      mainTableFieldList.length > new Set(mainTableFieldList).size
    ) {
      notification.error({
        message: t('提示'),
        description: t('主表中有组件绑定相同字段！'),
      }); //提示消息
      return false;
    }
    if (designType!.value === 'data' && subTableHasSameField()) {
      notification.error({
        message: t('提示'),
        description: t('子表中有组件绑定相同字段！'),
      }); //提示消息
      return false;
    }
    //判断隐藏组件是否填写完整
    if (formJson.hiddenComponent?.length) {
      const isCompelete = formJson.hiddenComponent.every((com) => {
        return Object.values(com).every((val) => val !== '');
      });
      if (!isCompelete) {
        notification.error({
          message: t('提示'),
          description: t('隐藏组件需填写完整'),
        }); //提示消息
        return false;
      }
    }

    //一个个组件遍历
    const message = validateComponent(formJson.list);

    if (message) {
      notification.error({
        message: t('提示'),
        description: message,
      }); //提示消息
      return false;
    }

    return true;
  };

  const validateComponent = (list: ComponentOptionModel[]) => {
    for (const component of list) {
      //布局组件需要递归子集
      if (['card', 'tab', 'form', 'grid'].includes(component.type)) {
        //如果是子表单 默认取 children中的组件  其他的 都是取layout中的组件
        if (component.type === 'form') {
          if (!component.bindTable) {
            return t(`{name}(子表单)未绑定表`, { name: component.label });
          }

          if (!component.children || component.children.length === 0) {
            return t(`{name}(子表单)的子组件不能为空`, { name: component.label });
          }
          //如果子组件有错误  直接返回顶级
          const errorMsg = validateComponent(component.children);
          if (errorMsg) {
            return errorMsg;
          }
        } else {
          if (!component.layout || component.layout.length === 0) {
            return t(`{name}组件布局不能为空`, { name: component.label });
          }

          for (const item of component.layout) {
            const errorMsg = validateComponent(item.list);
            if (errorMsg) {
              return errorMsg;
            }
          }
        }
      }
      if (
        noHaveTableAndField.includes(component.type) ||
        component.type === 'form' ||
        component.type === 'one-for-one'
      ) {
        //如果是不需要绑定字段的 默认跳过验证
        continue;
      }

      //如果是时间区间组件 必须要绑定2个字段  一个开始时间  一个结束时间
      if (component.type === 'range') {
        if (!component.bindStartTime) {
          return t(`{name}未绑定开始时间字段`, { name: component.label });
        }
        if (!component.bindEndTime) {
          return t(`{name}未绑定结束时间字段`, { name: component.label });
        }
      }

      //级联组件 必须选择级联配置
      if (component.type === 'cascader' && !component.options!.apiConfig.apiId) {
        return t(`{name}未选择级联配置`, { name: component.label });
      }

      //如果是远程组件并且是 数据源  或者 数据字典 方式
      if (
        remoteComponents.includes(component.type) &&
        component.options!.datasourceType !== 'staticData'
      ) {
        if (component.options!.datasourceType === 'dic') {
          if (!component.options!.itemId) {
            return t(`{name}未选择数据字典`, { name: component.label });
          }
          if (!component.options!.dicOptions?.length && component.type === 'associate-popup') {
            return t(`{name}未进行联想配置`, { name: component.label });
          }

          if (!component.options!.dicOptions?.length && component.type === 'multiple-popup') {
            return t(`{name}未进行显示配置`, { name: component.label });
          }
        }
        if (component.options!.datasourceType === 'api') {
          if (!component.options!.apiConfig.apiId) {
            return t(`{name}未选择API`, { name: component.label });
          }
          if (!component.options!.apiConfig.outputParams && component.type === 'associate-popup') {
            return t(`{name}未进行联想配置`, { name: component.label });
          }

          if (!component.options!.apiConfig.outputParams && component.type === 'multiple-popup') {
            return t(`{name}未进行显示配置`, { name: component.label });
          }
        }

        if (component.options!.datasourceType === 'datasource') {
          if (!component.options!.sourceId) {
            return t(`{name}未选择数据源`, { name: component.label });
          }
          if (!component.options!.labelField) {
            return t(`{name}未选择数据源显示字段`, { name: component.label });
          }
          if (!component.options!.valueField) {
            return t(`{name}未选择数据源保存字段`, { name: component.label });
          }
        }
      }
      // TODO  这里继续写各组件自己特有的一些验证

      if (!component.bindTable) {
        return t(`{name}未绑定表`, { name: component.label });
      }

      if (!component.bindField && !component.type.includes('range')) {
        return t(`{name}未绑定字段`, { name: component.label });
      }

      if (
        component.type.includes('range') &&
        (!component.bindStartTime || !component.bindEndTime)
      ) {
        return t(`{name}未绑定开始字段或结束字段`, { name: component.label });
      }
      if (component.type === 'auto-code' && !component.options!.autoCodeRule) {
        return t(`{name}未选择编码规则`, { name: component.label });
      }
    }
    return '';
  };

  //遍历所有组件 是否有子表单
  const sumSubFormComponent = (list: ComponentOptionModel[]): number => {
    let totalSubForm = 0;
    for (const component of list) {
      if (component.type === 'form' || component.type === 'one-for-one') {
        totalSubForm++;
      }

      //布局组件需要递归子集
      if (['card', 'tab', 'grid'].includes(component.type)) {
        //如果是子表单 默认取 children中的组件  其他的 都是取layout中的组件
        if (!component.layout || component.layout.length === 0) {
          continue;
        }
        for (const item of component.layout) {
          totalSubForm += sumSubFormComponent(item.list);
        }
      }
    }
    return totalSubForm;
  };
  defineExpose({ validateStep });
</script>
